package com.jbp.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.jbp.exception.RRException;
import com.jbp.model.LoginParam;
import com.jbp.model.User;
import com.jbp.model.UserBlack;
import com.jbp.redis.RedisConfigService;
import com.jbp.service.*;
import com.jbp.utils.Constant;
import com.jbp.utils.R;
import com.jbp.utils.StrToMillsUtil;
import com.jbp.utils.encryptUtils.RsaEncryptUtil;
import io.swagger.annotations.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.Map;

@Api(tags ="APP接口--用户登陆 注册相关接口" ,hidden = true)
@RestController
@RequestMapping(value = "")
public class LoginController{
    @Autowired
    private UserService userService;

    @Autowired
    private RedisConfigService redisConfigService;

    @Autowired
    private UserBlackService userBlackService;
    @Autowired
    private AccountService accountService;
    @Autowired
    private LoginService loginService;
    @Autowired
    private PropertyService propertyService;
    @Autowired
    private BlackIpService blackIpService;

    @Autowired
    private BlackDeviceService blackDeviceService;


    @ApiOperation(value="登录",notes="用户登录")
    @ApiResponses({
            @ApiResponse(code = 200,message = "登录成功",response = User.class),
            @ApiResponse(code = 201,message = "返回失败信息")
    })
    @ApiImplicitParams({
            @ApiImplicitParam(name = "mobile",value = "账号",paramType = "query"),
            @ApiImplicitParam(name="password",value = "密码",paramType = "query"),
            @ApiImplicitParam(name="device",value = "设备号",paramType = "query"),
            @ApiImplicitParam(name="messageCode",value = "验证码",paramType = "query"),
            @ApiImplicitParam(name = "type",value = "登录类型",paramType = "query")
    })
    @PostMapping("/login")
    public R login(@RequestBody User user,
                   @RequestHeader("deviceType") String deviceType,
                   @RequestHeader("deviceInfo") String deviceInfo,
                   @RequestHeader("channel") String channel,
                   @RequestHeader("appVersion") String appVersion){
        if (StringUtils.isEmpty(user.getMobile())){
            return R.error("账号不能为空");
        }
        if (StringUtils.isEmpty(user.getType())){
            return R.error("登录类型不能为空");
        }
        if (StringUtils.isEmpty(user.getDevice())){
            return R.error("设备号不能为空");
        }

        User usercheck=userService.getOne(new QueryWrapper<User>().eq("mobile",user.getMobile()));

        //记录原记录登录设备
        String device=usercheck == null ? null : usercheck.getDevice();

        if(usercheck!=null && (blackDeviceService.isBlack(usercheck.getDevice()) || blackIpService.isBlack(usercheck.getIp()))) {
            throw new RRException("账号冻结中", 210);
        }

        if(blackDeviceService.isBlack(user.getDevice()) || blackIpService.isBlack(user.getIp())) {
            throw new RRException("账号冻结中", 210);
        }

        //设备锁开启
        if (device!=null && usercheck.getDeviceLock()==1) {
            /*if (!user.getDevice().equalsIgnoreCase(device)) {
                return R.error("设备锁开启，请用原设备登录");
            }*/
        }
        String loginType = "";
        if (user.getType().equals("note")){
            loginType = "短信";
            //短信登录
            if (org.apache.commons.lang.StringUtils.isEmpty(user.getMessageCode())){
                return R.error("验证码为空");
            }
            Object obj= redisConfigService.get(Constant.CODE_PREFIX+user.getMobile());
            if (obj == null){
                return R.error("请先发送验证码");
            }
            if (!obj.equals(user.getMessageCode())){
                return R.error("验证码不正确");
            }

            //验证码效验
            if (usercheck == null){
                usercheck = loginService.createUser(user);
            }
        }else{
            loginType = "密码";
            if (usercheck == null){
                return  R.error("账号不存在");
            }

            String key = "user:pass:trytimes:"+usercheck.getId();
            int tryTimes = redisConfigService.getInt(key);
            if (tryTimes>=5) {
                return R.error("密码已锁定，请用验证码登录");
            }

            String pass = propertyService.decrypt(user.getPassword());
            if (!StrToMillsUtil.passwordEncode(pass, usercheck.getSalt()).equals(usercheck.getPassword())){
                redisConfigService.set(key, tryTimes+1, 60*60L);
                if(5-tryTimes-1>0) {
                    return R.error("密码错误,再错" + (5 - tryTimes - 1) + "次将锁定1小时");
                } else {
                    return R.error("密码已锁定");
                }
            }
        }
//        usercheck.setDevice(user.getDevice());//不更新设备号信息20250903
        if (null == device || "".equals(device)){
            usercheck.setDevice(user.getDevice());
        }
        usercheck.setAesVipara(user.getAesVipara());
        usercheck.setAesKey(user.getAesKey());

        LoginParam loginParam = new LoginParam();
        loginParam.setDeviceType(deviceType);
        loginParam.setDeviceInfo(deviceInfo);
        loginParam.setChannel(channel);
        loginParam.setAppVersion(appVersion);
        return R.ok(loginService.login(usercheck, loginParam, loginType));
    }

    @ApiOperation(value="登录",notes="手机一键登录")
    @ApiResponses({
            @ApiResponse(code = 200,message = "登录成功",response = User.class),
            @ApiResponse(code = 201,message = "返回失败信息")
    })
    @ApiImplicitParams({
            @ApiImplicitParam(name="device",value = "设备号",paramType = "query"),
            @ApiImplicitParam(name="loginToken",value = "设备一键登录token",paramType = "query"),
    })
    @PostMapping("/localphone_login")
    public R localPhoneLogin(@RequestBody LoginParam loginParam,
                             @RequestHeader("deviceType") String deviceType,
                             @RequestHeader("deviceInfo") String deviceInfo,
                             @RequestHeader("channel") String channel,
                             @RequestHeader("appVersion") String appVersion){
        if (StringUtils.isEmpty(loginParam.getDevice()) || StringUtils.isEmpty(loginParam.getLoginToken())){
            return R.error("参数错误");
        }
        loginParam.setDeviceType(deviceType);
        loginParam.setDeviceInfo(deviceInfo);
        loginParam.setChannel(channel);
        loginParam.setAppVersion(appVersion);
        User user = loginService.localPhoneLogin(loginParam);
        return R.ok(user);
    }

    @ApiOperation(value="登录",notes="微信登录")
    @ApiResponses({
            @ApiResponse(code = 200,message = "登录成功",response = User.class),
            @ApiResponse(code = 201,message = "返回失败信息")
    })
    @ApiImplicitParams({
            @ApiImplicitParam(name="device",value = "设备号",paramType = "query"),
            @ApiImplicitParam(name="code",value = "code",paramType = "query"),
    })
    @PostMapping("/wechatLogin")
    public R wechatLogin(@RequestBody LoginParam loginParam,
                         @RequestHeader("deviceType") String deviceType,
                         @RequestHeader("deviceInfo") String deviceInfo,
                         @RequestHeader("channel") String channel,
                         @RequestHeader("appVersion") String appVersion){
        if (StringUtils.isEmpty(loginParam.getDevice()) || StringUtils.isEmpty(loginParam.getCode())){
            return R.error("参数错误");
        }
        User user = loginService.wechatLogin(loginParam);
        loginParam.setDeviceType(deviceType);
        loginParam.setDeviceInfo(deviceInfo);
        loginParam.setChannel(channel);
        loginParam.setAppVersion(appVersion);
        return R.ok(user);
    }

    @PostMapping("/appleLogin")
    public R appleLogin(@RequestBody LoginParam loginParam,
                        @RequestHeader("deviceType") String deviceType,
                        @RequestHeader("deviceInfo") String deviceInfo,
                        @RequestHeader("channel") String channel,
                        @RequestHeader("appVersion") String appVersion){

        if (StringUtils.isEmpty(loginParam.getDevice()) || StringUtils.isEmpty(loginParam.getAppleUserId())){
            return R.error("参数错误");
        }
        loginParam.setAppleUserId(decryptAppleUserId(loginParam.getAppleUserId()));
        loginParam.setDeviceType(deviceType);
        loginParam.setDeviceInfo(deviceInfo);
        loginParam.setChannel(channel);
        loginParam.setAppVersion(appVersion);
        User user = loginService.appleLogin(loginParam);
        return R.ok(user);
    }

    //解密出手机号
    private String decryptAppleUserId(String encodeStr) {
        try {
            String privateKey = propertyService.getV("encrypt_private_key");
            String appleUserId = RsaEncryptUtil.decrypt(encodeStr, privateKey);
            if (appleUserId==null) {
                throw new RRException("解析失败");
            }
            return appleUserId;
        } catch (Exception e) {
            throw new RRException("解析失败");
        }
    }

    @ApiOperation(value="登录",notes="qq登录")
    @ApiResponses({
            @ApiResponse(code = 200,message = "登录成功",response = User.class),
            @ApiResponse(code = 201,message = "返回失败信息")
    })
    @ApiImplicitParams({
            @ApiImplicitParam(name="device",value = "设备号",paramType = "query"),
            @ApiImplicitParam(name="code",value = "code",paramType = "query"),
    })
    @PostMapping("/qqLogin")
    public R qqLogin(@RequestBody LoginParam loginParam,
                     @RequestHeader("deviceType") String deviceType,
                     @RequestHeader("deviceInfo") String deviceInfo,
                     @RequestHeader("channel") String channel,
                     @RequestHeader("appVersion") String appVersion){
        if (StringUtils.isEmpty(loginParam.getDevice()) || StringUtils.isEmpty(loginParam.getOpenid())
                || StringUtils.isEmpty(loginParam.getAccess_token())){
            return R.error("参数错误");
        }
        loginParam.setDeviceType(deviceType);
        loginParam.setDeviceInfo(deviceInfo);
        loginParam.setChannel(channel);
        loginParam.setAppVersion(appVersion);
        User user = loginService.qqLogin(loginParam);
        return R.ok(user);
    }

    @ApiOperation(value="账号密码登录验证是否需要发送验证码",notes="账号密码登录",hidden = true)
    @ApiResponses({
            @ApiResponse(code = 200,message = "true false  返回true需要短信验证"),
            @ApiResponse(code = 201,message = "返回失败信息")
    })
    @ApiImplicitParams({
            @ApiImplicitParam(name = "mobile",value = "账号",paramType = "query"),
            @ApiImplicitParam(name="password",value = "密码",paramType = "query"),
            @ApiImplicitParam(name="device",value = "设备号",paramType = "query"),
    })
    @GetMapping("/isloginVerify")
    public R isloginVerify(@RequestBody User user){
        if (StringUtils.isEmpty(user.getMobile())){
            return R.error("账号不能为空");
        }
        if (StringUtils.isEmpty(user.getDevice())){
            return R.error("设备号不能为空");
        }
        if (StringUtils.isEmpty(user.getPassword())){
            return R.error("密码不能为空");
        }
        User usercheck=userService.getOne(new QueryWrapper<User>().eq("mobile",user.getMobile()));
        if (usercheck == null){
            return R.error("账号不存在");
        }
        if (!StrToMillsUtil.passwordEncode(user.getPassword(),usercheck.getSalt()).equals(usercheck.getPassword())){
            return R.error("密码不正确");
        }
        if (user.getDevice().equals(usercheck.getDevice())){
            return R.ok().put("data",false);
        }
        return R.ok().put("data",true);
    }


    @ApiOperation(value="退出登录",notes="退出登录")
    @ApiResponses({
            @ApiResponse(code = 200,message = "成功"),
            @ApiResponse(code = 201,message = "返回失败信息")
    })
    @ApiImplicitParams({
            @ApiImplicitParam(name ="token",value = "token",paramType = "query"),
            @ApiImplicitParam(name="sessionId",value = "sessionId",paramType = "query"),
    })

    @PostMapping("/rest/loginOut")
    public R loginOut(@RequestAttribute("userId") Integer userId){
        //清除缓存
        User user=userService.getById(userId);
        UserBlack black= userBlackService.getOne(Wrappers.<UserBlack>lambdaQuery().eq(UserBlack::getUserId,user).eq(UserBlack::getDevice,user.getDevice()));
        if (black == null){
            black=new UserBlack();
            black.setType("white");
            black.setCreateTime(new Date());
            black.setUserId(user.getId());
            black.setDevice(user.getDevice());
            userBlackService.save(black);
        }else{
            black.setType("white");
            black.setCreateTime(new Date());
            userBlackService.updateById(black);
        }
        redisConfigService.remove(user.getUuid());
        user.setIsOnline("offline");
        userService.updateById(user);
        return R.ok();
    }


}
